using SqlSugar;
using IM.Easy.Core.Services;
using IM.Easy.Core.Utils;
using IM.Easy.Infrastructure.Query;
using IM.Easy.Core.Extensions;
using IM.Easy.Entity.System;
using IM.Easy.SystemServices.Dtos;
using IM.Easy.SystemServices.IServices;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Mvc.Controllers;
using IM.Easy.Core.Cache;
using IM.Easy.Core.AppContext;
using Microsoft.AspNetCore.Mvc.Abstractions;
using System.Reflection;
using Microsoft.AspNetCore.Http;
using System.IO;
using IM.Easy.Core.Attributes;

namespace IM.Easy.SystemServices.Services
{
    public class ApiPermissionsService : AppServices<ApiPermissions>, IApiPermissionsService
    {
        private readonly EndpointDataSource _endpointDataSource;
        public ApiPermissionsService(ISqlSugarClient db, EndpointDataSource endpointDataSource) : base(db)
        {
            _endpointDataSource = endpointDataSource;
        }

        public ApiPermissions GetById(long id)
        {
            // TODO: 添加获取逻辑
            return Context.Queryable<ApiPermissions>().InSingle(id);
        }

        /// <summary>
        /// 获取路由信息
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public ApiPermissions GetApi(string path, string method)
        {
            ApiPermissions api = GetFirst(s => s.Path == path && s.HttpMethod == method);
            return api;
        }


        /// <summary>
        /// 优先从缓存中获取
        /// </summary>
        /// <returns></returns>
        public List<ApiPermissions> GetPermissions()
        {
            var permissions = GetList();
            return permissions;
        }

        public PageResponse<ApiPermissions> GetPageList(ApiPermissionsQueryDto query)
        {
            var queryable = Context.Queryable<ApiPermissions>();
            var exp = Expressionable.Create<ApiPermissions>();
            exp = exp.AndIF(!string.IsNullOrEmpty(query.Path), s => s.Path.Contains(query.Path))
                    .AndIF(query.IsEnabled.HasValue, s => s.IsEnabled == query.IsEnabled)
                    .AndIF(!string.IsNullOrEmpty(query.Name), s => s.Name.Contains(query.Name))
                    .AndIF(!string.IsNullOrEmpty(query.PermissionKey), s => s.PermissionKey.Contains(query.PermissionKey));
            var page = queryable
                 .Where(exp.ToExpression())
                 .OrderByDescending(s => s.CreatedAt)
                 .OrderByDescending(s => s.Path)
                 .ToPageList<ApiPermissions, ApiPermissions>(query);
            return page;
        }

        /// <summary>
        /// 更新接口
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public override bool Update(ApiPermissions entity)
        {
            if (!Validate(entity, out string msg)) ExceptionUtils.ThrowBusinessException(msg);
            return base.Update(entity);
        }

        /// <summary>
        /// 校验权限标识是否重复
        /// </summary>
        /// <param name="roleId"></param>
        /// <param name="perm"></param>
        /// <returns></returns>
        private bool PermDuplicate(long roleId, string perm, out string msg)
        {
            bool exist = Context.Queryable<ApiPermissions>()
                                .Any(r => r.PermissionKey == perm && r.Id != roleId && r.AuthRequired);
            msg = exist ? $"权限标识 【{perm}】 重复，请更换后重试。" : "校验成功";
            return exist;
        }

        /// <summary>
        /// 接口合法性校验
        /// </summary>
        /// <param name="apiPermissions">接口权限实体，包含接口权限相关信息</param>
        /// <param name="msg">用于返回校验结果的详细信息，如校验成功或失败的具体原因</param>
        /// <returns>true 表示校验通过；false 表示校验失败</returns>
        public bool Validate(ApiPermissions apiPermissions, out string msg)
        {
            msg = "校验成功";
            if (string.IsNullOrWhiteSpace(apiPermissions.PermissionKey)) return true;
            if (PermDuplicate(apiPermissions.Id, apiPermissions.PermissionKey, out msg)) return false;
            return true;
        }


        public bool Delete(params long[] Id)
        {
            // TODO: 添加删除逻辑
            return Context.Deleteable<ApiPermissions>(Id).ExecuteCommandHasChange();
        }

        /// <summary>
        /// 扫描后暴力同步
        /// </summary>
        /// <returns></returns>
        public void ScanAndSync()
        {
            var endpoints = _endpointDataSource.Endpoints
            .OfType<RouteEndpoint>()
            .Where(endpoint => endpoint.Metadata.OfType<ControllerActionDescriptor>().Any()) // 排除非控制器终结点
            .Select(endpoint => new ApiPermissions
            {
                Path = endpoint.RoutePattern.RawText,
                HttpMethod = endpoint.Metadata
                    .OfType<HttpMethodMetadata>()
                    .FirstOrDefault()?.HttpMethods.FirstOrDefault() ?? "GET",
                IsEnabled = false      // 默认禁用
            })
            .ToList();
            var oldEndpoints = GetList();

            var diff = Diff(endpoints, oldEndpoints);


            InsertRange(diff.Added);
            Delete(diff.Deleted);
        }



        /// <summary>
        /// 接口扫描
        /// </summary>
        public List<RouteEndpoint> ScanEndpoint()
        {
            var endpoints = _endpointDataSource.Endpoints
                            .OfType<RouteEndpoint>()
                            .Where(endpoint => endpoint.Metadata.OfType<ControllerActionDescriptor>().Any()) // 排除非控制器终结点
                            .ToList();
            return endpoints;
        }

        public DiffApiPermissions Diff(List<ApiPermissions> newData, List<ApiPermissions> oldData)
        {
            // 查找新增的记录
            var added = newData.Where(newItem => !oldData.Any(oldItem => oldItem.Path == newItem.Path && oldItem.HttpMethod == newItem.HttpMethod)).ToList();

            // 查找删除的记录
            var deleted = oldData.Where(oldItem => !newData.Any(newItem => newItem.Path == oldItem.Path && oldItem.HttpMethod == newItem.HttpMethod)).ToList();

            return new DiffApiPermissions { Added = added, Deleted = deleted };
        }

        /// <summary>
        /// 转化成数据库实体
        /// </summary>
        /// <param name="endpoints"></param>
        /// <returns></returns>
        public List<ApiPermissions> Convert(List<RouteEndpoint> endpoints)
        {
            var apiPermissions = endpoints.Select(endpoint =>
            {
                // 获取控制器动作描述符
                var actionDescriptor = endpoint.Metadata
                    .OfType<ControllerActionDescriptor>()
                    .FirstOrDefault();

                if (actionDescriptor == null)
                {
                    return null;
                }
                var methodInfo = actionDescriptor.MethodInfo;
                var apiDescAttribute = methodInfo.GetCustomAttribute<ApiAttribute>();
                return new ApiPermissions
                {
                    Path = endpoint.RoutePattern.RawText,
                    HttpMethod = endpoint.Metadata
                        .OfType<HttpMethodMetadata>()
                        .FirstOrDefault()?.HttpMethods.FirstOrDefault() ?? "GET",
                    IsEnabled = apiDescAttribute?.Required ?? false,  // 是否启用
                    Name = apiDescAttribute?.Name, // 从特性中获取值
                    Desc = apiDescAttribute?.Desc, // 描述
                    PermissionKey = apiDescAttribute?.Perm,// 权限
                    AuthRequired = !apiDescAttribute?.AllowAnonymous ?? true,
                    IsTrack = apiDescAttribute?.TrackLog ?? false,
                };
            }).Where(api => api != null) // 过滤掉空结果
              .ToList();
            return apiPermissions;
        }

        /// <summary>
        /// 设置状态
        /// </summary>
        /// <param name="status"></param>
        /// <param name="ids"></param>
        /// <returns></returns>
        public int SetStatus(bool status, params long[] ids)
        {
            var count = Context.Updateable<ApiPermissions>()
                .SetColumns(s => s.IsEnabled == status)
                .Where(s => ids.Contains(s.Id))
                .ExecuteCommand();
            return count;
        }

        /// <summary>
        /// 设置日志记录状态
        /// </summary>
        /// <param name="track"></param>
        /// <param name="ids"></param>
        /// <returns></returns>
        public int SetTrack(bool track, params long[] ids)
        {
            var count = Context.Updateable<ApiPermissions>()
                   .SetColumns(s => s.IsTrack == track)
                   .Where(s => ids.Contains(s.Id))
                   .ExecuteCommand();
            return count;
        }


        /// <summary>
        /// 获取下拉选项列表
        /// </summary>
        /// <param name="keyword"></param>
        /// <returns></returns>
        public List<ApiPermissions> GetOptionList(string keyword)
        {
            var queryable = Context.Queryable<ApiPermissions>();
            var exp = Expressionable.Create<ApiPermissions>();
            exp = exp.And(s => !string.IsNullOrEmpty(s.PermissionKey))
                      .And(s => !string.IsNullOrEmpty(s.Name))
                      .And(s => s.AuthRequired)
                      .AndIF(!string.IsNullOrWhiteSpace(keyword), s => (s.PermissionKey.Contains(keyword) || s.Name.Contains(keyword)));

            List<ApiPermissions> list = Context.Queryable<ApiPermissions>()
                                                .Where(exp.ToExpression())
                                                .ToList();
            return list;
        }
    }
}
